package com.syh.jn.scm.infrastructure.repository.impl.operation.financial;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import com.syh.core.ddd.infrastructure.repository.AbstractAggregateRepository;
import com.syh.core.expction.DataModelException;
import com.syh.jn.scm.domain.operation.entity.financial.Financial;
import com.syh.jn.scm.domain.operation.entity.financial.FinancialAccount;
import com.syh.jn.scm.domain.operation.entity.financial.FinancialAddress;
import com.syh.jn.scm.domain.operation.entity.financial.FinancialContact;
import com.syh.jn.scm.domain.operation.repository.financial.FinancialRepository;
import com.syh.jn.scm.dto.operation.financial.FinancialAddressVo;
import com.syh.jn.scm.dto.operation.financial.FinancialVo;
import com.syh.jn.scm.infrastructure.repository.model.base.BusinessEntityAddressModel;
import com.syh.jn.scm.infrastructure.repository.model.base.financial.FinanceModel;
import com.syh.jn.scm.infrastructure.repository.model.base.financial.SupplierFinanceModel;
import com.syh.jn.scm.infrastructure.repository.model.system.AccountModel;
import com.syh.jn.scm.infrastructure.repository.utils.SQLAliasGenerateUtil;
import org.apache.ibatis.jdbc.SQL;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;

/**
 * 运营端金融机构仓储
 */
@Repository
public class FinancialRepositoryImpl extends AbstractAggregateRepository<Financial, FinanceModel, Long> implements FinancialRepository {
  /**
   * 运营端新增金融机构
   *
   * @param financial
   * @return
   */
  @Override
  public Long add(Financial financial) {
    Long id = super.add(financial);
    this.saveAddress(id, financial.getAddressItem());
    return id;
  }

  /**
   * 运营端修改金融机构
   *
   * @param financial
   */
  @Override
  public void update(Financial financial) {
    super.update(financial);
    //删除地址项
    this.removeAddress(financial);
    //保存新的地址项
    this.saveAddress(financial.getId(), financial.getAddressItem());
  }

  /**
   * 删除地址项
   *
   * @param financial
   */
  private void removeAddress(Financial financial) {
    StringBuffer hql = new StringBuffer();
    hql.append("from BusinessEntityAddressModel model where model.businessEntityId = ?  and model.terminalType = 'FINANCIAL'");
    List<BusinessEntityAddressModel> addressModelList = (List<BusinessEntityAddressModel>) this.hibernateTemplate.find(hql.toString(), financial.getId());
    addressModelList.stream().forEach(item -> {
      this.hibernateTemplate.delete(item);
    });
  }

  /**
   * 保存地址项
   *
   * @param id
   * @param addresses
   */
  private void saveAddress(Long id, List<FinancialAddress> addresses) {
    addresses.stream().forEach(item -> {
      BusinessEntityAddressModel addressModel = new BusinessEntityAddressModel();
      ExtBeanUtils.copyProperties(item, addressModel);
      addressModel.setBusinessEntityId(id);
      addressModel.setTerminalType("FINANCIAL");
      this.hibernateTemplate.save(addressModel);
    });
  }

  /**
   * 删除
   *
   * @param financial
   */
  @Override
  public void remove(Financial financial) {
    //删除主项
    super.removeById(financial.getId());
    //删除地址项
    this.removeAddress(financial);
  }

  /**
   * 停用
   *
   * @param financial
   */
  @Override
  public void disabled(Financial financial) {
    super.update(financial);
  }

  /**
   * 启用
   *
   * @param financial
   */
  @Override
  public void enabled(Financial financial) {
    super.update(financial);
  }

  /**
   * 关联供应商
   *
   * @param id
   * @param contact
   */
  @Override
  public void contact(Long id, FinancialContact contact) {
    ExtAssert.notNull(id, "id不能为空");
    ExtAssert.notNull(contact, "关联供应商对象不能为空");

    StringBuffer hql = new StringBuffer();
    hql.append("from SupplierFinanceModel model where model.supplierId = ? and model.businessEntityId = ?");
    List<SupplierFinanceModel> modelList = (List<SupplierFinanceModel>) this.hibernateTemplate.find(hql.toString(), contact.getSupplierId(), id);
    if (modelList != null && modelList.size() > 0) {
      throw new DataModelException("该金融机构已经关联该供应商,不能再次关联");
    }
    SupplierFinanceModel model = new SupplierFinanceModel();
    ExtBeanUtils.copyProperties(contact, model);
    super.hibernateTemplate.save(model);
  }

  /**
   * 添加金融账号
   *
   * @param account
   * @return
   */
  @Override
  public Boolean addAccount(FinancialAccount account) {
    ExtAssert.notNull(account, "缺少必要参数");

    StringBuffer hql = new StringBuffer();
    hql.append("from AccountModel model where model.businessEntityId = ?  and model.terminalType = 'FINANCIAL' ");
    List<AccountModel> modelList = (List<AccountModel>) this.hibernateTemplate.find(hql.toString(), account.getBusinessEntityId());
    if (modelList != null && modelList.size() > 0) {
      throw new DataModelException("该金融机构已经有账号不能再次添加");
    }
    AccountModel accountModel = new AccountModel();
    ExtBeanUtils.copyProperties(account, accountModel, false);
    super.hibernateTemplate.save(accountModel);
    return Boolean.TRUE;
  }

  /**
   * 根据id获取金融地址
   *
   * @param id
   * @return
   */
  @Override
  public List<FinancialAddressVo> getAddress(Long id) {
    StringBuffer hql = new StringBuffer();
    hql.append("from BusinessEntityAddressModel model where model.businessEntityId = ? and model.terminalType = 'FINANCIAL'");
    List<BusinessEntityAddressModel> model = (List<BusinessEntityAddressModel>) this.hibernateTemplate.find(hql.toString(), id);
    List<FinancialAddress> addressList = new ArrayList<>();
    model.stream().forEach(item -> {
      FinancialAddress address = new FinancialAddress();
      ExtBeanUtils.copyProperties(item, address);
      addressList.add(address);
    });
    return this.transformFinancial(addressList);
  }

  /**
   * 内部方法  业务模型转FinancialAddressVo
   *
   * @param entityList
   * @return
   */
  private List<FinancialAddressVo> transformFinancial(List<FinancialAddress> entityList) {
    List<FinancialAddressVo> voList = new ArrayList<>();
    entityList.stream().forEach((entity) -> {
      FinancialAddressVo vo = new FinancialAddressVo();
      ExtBeanUtils.copyProperties(entity, vo);
      voList.add(vo);
    });
    return voList;
  }

  @Override
  protected SQL getViewSql() {
    return new SQL() {{
      SELECT(SQLAliasGenerateUtil.aliasGenerate(FinancialVo.class, "finance", null));
      FROM(getModelTableName(FinanceModel.class) + " finance ");
    }};
  }
}
